package com.tsh.chat.util;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.tsh.chat.V4Test;
import com.zhipu.oapi.ClientV4;
import com.zhipu.oapi.Constants;
import com.zhipu.oapi.service.v4.model.*;
import io.reactivex.Flowable;
import org.apache.ibatis.mapping.Environment;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.time.Duration;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
public class ChatUtil {
    private final static Logger logger = LoggerFactory.getLogger(V4Test.class);

    private static final String API_SECRET_KEY = "4f0c5d4deb30da79cd93a2bec6779352.EJB0QHwN9zGFuqV3";

    private static final ClientV4 client = new ClientV4.Builder(API_SECRET_KEY)
            .enableTokenCache()
            .networkConfig(300, 100, 100, 100, TimeUnit.SECONDS)
            .connectionPool(new okhttp3.ConnectionPool(8, 1, TimeUnit.SECONDS))
            .build();

    // 请自定义自己的业务id
    private static final String requestIdTemplate = "tsh-%d";

    private static final ObjectMapper mapper = defaultObjectMapper();

    public static ObjectMapper defaultObjectMapper() {
        ObjectMapper mapper = new ObjectMapper();
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        mapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
        return mapper;
    }

    /**
     * sse-V4：function调用
     */
    public static String testFunctionSSE(String messageContent) throws JsonProcessingException {
        List<ChatMessage> messages = new ArrayList<>();
        ChatMessage chatMessage = new ChatMessage(ChatMessageRole.USER.value(), messageContent);
        messages.add(chatMessage);
        String requestId = String.format(requestIdTemplate, System.currentTimeMillis());

        // 函数调用参数构建部分
        List<ChatTool> chatToolList = new ArrayList<>();
//        ChatTool chatTool = new ChatTool();
//        chatTool.setType(ChatToolType.FUNCTION.value());
//        ChatFunctionParameters chatFunctionParameters = new ChatFunctionParameters();
//        chatFunctionParameters.setType("object");
//        Map<String, Object> properties = new HashMap<>();
//        properties.put("location", new HashMap<String, Object>() {{
//            put("type", "string");
//            put("description", "城市，如：北京");
//        }});
//        properties.put("unit", new HashMap<String, Object>() {{
//            put("type", "string");
//            put("enum", new ArrayList<String>() {{
//                add("celsius");
//                add("fahrenheit");
//            }});
//        }});
//        chatFunctionParameters.setProperties(properties);
//        ChatFunction chatFunction = ChatFunction.builder()
//                .name("get_weather")
//                .description("Get the current weather of a location")
//                .parameters(chatFunctionParameters)
//                .build();
//        chatTool.setFunction(chatFunction);
//        chatToolList.add(chatTool);

        HashMap<String, Object> extraJson = new HashMap<>();

        //采样温度，控制输出的随机性，值越大随机性越强，默认值为0.95
        extraJson.put("temperature", 0.8);

        //单次响应tokens数限制，数值越大响应内容上限越大
        extraJson.put("max_tokens", 1024);

        ChatCompletionRequest chatCompletionRequest = ChatCompletionRequest.builder()
                .model(Constants.ModelChatGLM4)
                .stream(Boolean.TRUE)
                .messages(messages)
                .requestId(requestId)
                .tools(chatToolList)
                .toolChoice("auto")
                .extraJson(extraJson)
                .build();
        ModelApiResponse sseModelApiResp = client.invokeModelApi(chatCompletionRequest);

        StringBuilder responseContent = new StringBuilder();

        if (sseModelApiResp.isSuccess()) {
            AtomicBoolean isFirst = new AtomicBoolean(true);
            List<Choice> choices = new ArrayList<>();
            ChatMessageAccumulator chatMessageAccumulator = mapStreamToAccumulator(sseModelApiResp.getFlowable())
                    .doOnNext(accumulator -> {
                        if (isFirst.getAndSet(false)) {
                            System.out.println("Response:");
                        }
                        if (accumulator.getDelta() != null && accumulator.getDelta().getTool_calls() != null) {
                            String jsonString = mapper.writeValueAsString(accumulator.getDelta().getTool_calls());
                            logger.info("tool_calls: {}", jsonString);
                            //responseContent.append("tool_calls: ").append(jsonString).append("\n");
                        }
                        if (accumulator.getDelta() != null && accumulator.getDelta().getContent() != null) {
                            String content = accumulator.getDelta().getContent();
                            System.out.print(content);
                            responseContent.append(content);
                        }
                        choices.add(accumulator.getChoice());
                    })
                    .doOnComplete(System.out::println)
                    .lastElement()
                    .blockingGet();

            ModelData data = new ModelData();
            data.setChoices(choices);
            data.setUsage(chatMessageAccumulator.getUsage());
            data.setId(chatMessageAccumulator.getId());
            data.setCreated(chatMessageAccumulator.getCreated());
            data.setRequestId(chatCompletionRequest.getRequestId());
            sseModelApiResp.setFlowable(null);// 打印前置空
            sseModelApiResp.setData(data);
        }

        logger.info("model output: {}", mapper.writeValueAsString(sseModelApiResp));

        return responseContent.toString();
    }

    /**
     * sse-V4：连续对话
     */
    public static String constantChatSSE(List<ChatMessage> messageContent) throws JsonProcessingException {
        String requestId = String.format(requestIdTemplate, System.currentTimeMillis());

        HashMap<String, Object> extraJson = new HashMap<>();

        /**
         * 通过函数调用进行参数构建
         */
        List<ChatTool> chatToolList = new ArrayList<>();//创建工具类数组

        /**
         * 获取当前时间工具
         */
        ChatTool timeTool = new ChatTool();

        timeTool.setType(ChatToolType.FUNCTION.value());
        ChatFunctionParameters chatFunctionParameters = new ChatFunctionParameters();
        chatFunctionParameters.setType("object");
        Map<String, Object> properties = new HashMap<>();
        properties.put("current time", new HashMap<String, Object>() {{
            put("type", "string");
            put("description", "当前时间");
            put("value", System.currentTimeMillis());
        }});
        properties.put("format", new HashMap<String, Object>() {{
            put("type", "string");
            put("description", "时间格式，如：yyyy-MM-dd HH:mm:ss");
        }});
        chatFunctionParameters.setProperties(properties);
        chatFunctionParameters.setRequired(Arrays.asList("current time", "format"));
        ChatFunction chatFunction = ChatFunction.builder()
                .name("get_current_time")
                .description("Get the current time in a specified format")
                .parameters(chatFunctionParameters)
                .build();
        timeTool.setFunction(chatFunction);


        /**
         * 判断当前请求类型
         */

        chatToolList.add(timeTool);//添加到工具类数组
        /**
         * 函数调用参数构建结束
         */

        //采样温度，控制输出的随机性，值越大随机性越强
        //extraJson.put("temperature", 0.5);
        //单次响应tokens数限制，数值越大响应内容上限越大
        extraJson.put("max_tokens", 4095);

        ChatCompletionRequest chatCompletionRequest = ChatCompletionRequest.builder()
                .model(Constants.ModelChatGLM4)
                .stream(Boolean.TRUE)
                .messages(messageContent)
                .requestId(requestId)
                .toolChoice("auto")
                .extraJson(extraJson)
                .build();
        ModelApiResponse sseModelApiResp = client.invokeModelApi(chatCompletionRequest);

        StringBuilder responseContent = new StringBuilder();

        if (sseModelApiResp.isSuccess()) {
            AtomicBoolean isFirst = new AtomicBoolean(true);
            List<Choice> choices = new ArrayList<>();
            ChatMessageAccumulator chatMessageAccumulator = mapStreamToAccumulator(sseModelApiResp.getFlowable())
                    .doOnNext(accumulator -> {
                        if (isFirst.getAndSet(false)) {
                            System.out.println("Response:");
                        }
                        if (accumulator.getDelta() != null && accumulator.getDelta().getTool_calls() != null) {
                            String jsonString = mapper.writeValueAsString(accumulator.getDelta().getTool_calls());
                            System.out.println(accumulator.getDelta().getRole());
                            logger.info("tool_calls: {}", jsonString);
                            //responseContent.append("tool_calls: ").append(jsonString).append("\n");
                        }
                        if (accumulator.getDelta() != null && accumulator.getDelta().getContent() != null) {
                            String content = accumulator.getDelta().getContent();
                            System.out.print(content);
                            responseContent.append(content);
                        }
                        choices.add(accumulator.getChoice());
                    })
                    .doOnComplete(System.out::println)
                    .lastElement()
                    .blockingGet();

            ModelData data = new ModelData();
            data.setChoices(choices);
            data.setUsage(chatMessageAccumulator.getUsage());
            data.setId(chatMessageAccumulator.getId());
            data.setCreated(chatMessageAccumulator.getCreated());
            data.setRequestId(chatCompletionRequest.getRequestId());
            sseModelApiResp.setFlowable(null);// 打印前置空
            sseModelApiResp.setData(data);
        }

        logger.info("model output: {}", mapper.writeValueAsString(sseModelApiResp));

        return responseContent.toString();
    }

    /**
     * 更新人设描述
     */
    public static String updateCharacterDescSSE(String oldDesc, String promptDesc, Date oldTime, Date now) throws JsonProcessingException {
        List<ChatMessage> messages = new ArrayList<>();
        ChatMessage baseMessage = new ChatMessage(ChatMessageRole.SYSTEM.value(), "请分析用户提供的文本内容，并仅输出你综合分析得到的人物设定描述。不要复述问题，直接开始回答。人物设定描述一般包括人物的名称、年龄、职业、居住地、性格特点、行为准则、语言风格、沟通方式等。若文本中没有提到对应的信息则暂定为未知，不能进行假设。避免任何解释。");
        messages.add(baseMessage);
        if(!oldDesc.isEmpty()){
            ChatMessage sysMessage = new ChatMessage(ChatMessageRole.SYSTEM.value(), "已知的人物设定描述:" + oldDesc + "\n统计时间:" + oldTime.toString());
            messages.add(sysMessage);
            ChatMessage userMessage = new ChatMessage(ChatMessageRole.USER.value(),   "文本内容:" + promptDesc + "\n当前时间:" + now.toString());
            messages.add(userMessage);
        }else{
            ChatMessage userMessage = new ChatMessage(ChatMessageRole.USER.value(), "文本内容:" + promptDesc + "\n当前时间:" + now.toString());
            messages.add(userMessage);
        }
        String requestId = String.format(requestIdTemplate, System.currentTimeMillis());

        HashMap<String, Object> extraJson = new HashMap<>();

        //采样温度，控制输出的随机性，值越大随机性越强
        extraJson.put("temperature", 0.4);
        //单次响应tokens数限制，数值越大响应内容上限越大
        extraJson.put("max_tokens", 4095);

        ChatCompletionRequest chatCompletionRequest = ChatCompletionRequest.builder()
                .model(Constants.ModelChatGLM4)
                .stream(Boolean.TRUE)
                .messages(messages)
                .requestId(requestId)
                .toolChoice("auto")
                .extraJson(extraJson)
                .build();
        ModelApiResponse sseModelApiResp = client.invokeModelApi(chatCompletionRequest);

        StringBuilder responseContent = new StringBuilder();

        if (sseModelApiResp.isSuccess()) {
            AtomicBoolean isFirst = new AtomicBoolean(true);
            List<Choice> choices = new ArrayList<>();
            ChatMessageAccumulator chatMessageAccumulator = mapStreamToAccumulator(sseModelApiResp.getFlowable())
                    .doOnNext(accumulator -> {
                        if (isFirst.getAndSet(false)) {
                            System.out.println("Response:");
                        }
                        if (accumulator.getDelta() != null && accumulator.getDelta().getTool_calls() != null) {
                            String jsonString = mapper.writeValueAsString(accumulator.getDelta().getTool_calls());
                            logger.info("tool_calls: {}", jsonString);
                            //responseContent.append("tool_calls: ").append(jsonString).append("\n");
                        }
                        if (accumulator.getDelta() != null && accumulator.getDelta().getContent() != null) {
                            String content = accumulator.getDelta().getContent();
                            System.out.print(content);
                            responseContent.append(content);
                        }
                        choices.add(accumulator.getChoice());
                    })
                    .doOnComplete(System.out::println)
                    .lastElement()
                    .blockingGet();

            ModelData data = new ModelData();
            data.setChoices(choices);
            data.setUsage(chatMessageAccumulator.getUsage());
            data.setId(chatMessageAccumulator.getId());
            data.setCreated(chatMessageAccumulator.getCreated());
            data.setRequestId(chatCompletionRequest.getRequestId());
            sseModelApiResp.setFlowable(null);// 打印前置空
            sseModelApiResp.setData(data);
        }

        logger.info("model output: {}", mapper.writeValueAsString(sseModelApiResp));

        return responseContent.toString();
    }

    /**
     * 更新人物事迹
     */
    public static String updateCharacterAchievementSSE(String oldAchieve, String newAchieve, Date oldTime, Date now) throws JsonProcessingException {
        List<ChatMessage> messages = new ArrayList<>();

        /**
         * 这种形式下需要定期对所有人物事迹进行整理
         */
        ChatMessage systemMessage = new ChatMessage(ChatMessageRole.SYSTEM.value(), "已知当前时间:" + now.toString() + "\n请分析用户提供的文本内容，按照格式输出你整理出来的所有人物事迹。不要输出任何多余内容，不需要任何解释。用户提供的文本中可能没有提到社交关系，此时直接回答“----”。避免任何解释。\n输出格式:\n- 年份日期:(未知填不祥)\n  人物:\n  地点:(未知填不祥)\n  行为:\n  内心感想:");
        messages.add(systemMessage);
        ChatMessage userMessage = new ChatMessage(ChatMessageRole.USER.value(), "文本内容:" + newAchieve);
        messages.add(userMessage);

//        if(!oldAchieve.isEmpty()){
//            ChatMessage systemMessage = new ChatMessage(ChatMessageRole.SYSTEM.value(), "请分析用户提供的文本内容，结合已知的人物事迹提供更新后的人物事迹总结。不要复述问题，不需要任何开头直接回答。人物事迹条目包含以下内容:年份日期、人物、地点、行为，年份日期和地点可以没有。用户提供的文本中可能没有提到人物事迹，此时直接输出已知的人物事迹，若没有则回答“无”。避免任何解释。");
//            messages.add(systemMessage);
//            ChatMessage sysMessage = new ChatMessage(ChatMessageRole.SYSTEM.value(), "已知的人物事迹:" + oldAchieve + "\n统计时间:" + oldTime.toString());
//            messages.add(sysMessage);
//            ChatMessage userMessage = new ChatMessage(ChatMessageRole.USER.value(),   "文本内容:" + newAchieve + "\n当前时间:" + now.toString());
//            messages.add(userMessage);
//        }else{
//            ChatMessage systemMessage = new ChatMessage(ChatMessageRole.SYSTEM.value(), "请分析用户提供的文本内容，提供人物事迹总结。不要复述问题，不需要任何开头直接回答。人物事迹条目包含以下内容:年份日期、人物、地点、行为，年份日期和地点可以没有。用户提供的文本中可能没有提到人物事迹，此时直接回答“无”。避免任何解释。");
//            messages.add(systemMessage);
//            ChatMessage userMessage = new ChatMessage(ChatMessageRole.USER.value(), "文本内容:" + newAchieve + "\n当前时间:" + now.toString());
//            messages.add(userMessage);
//        }
        String requestId = String.format(requestIdTemplate, System.currentTimeMillis());

        HashMap<String, Object> extraJson = new HashMap<>();

        //采样温度，控制输出的随机性，值越大随机性越强
        extraJson.put("temperature", 0.4);
        //单次响应tokens数限制，数值越大响应内容上限越大
        extraJson.put("max_tokens", 2048);

        ChatCompletionRequest chatCompletionRequest = ChatCompletionRequest.builder()
                .model(Constants.ModelChatGLM4)
                .stream(Boolean.TRUE)
                .messages(messages)
                .requestId(requestId)
                .toolChoice("auto")
                .extraJson(extraJson)
                .build();
        ModelApiResponse sseModelApiResp = client.invokeModelApi(chatCompletionRequest);

        StringBuilder responseContent = new StringBuilder();

        if (sseModelApiResp.isSuccess()) {
            AtomicBoolean isFirst = new AtomicBoolean(true);
            List<Choice> choices = new ArrayList<>();
            ChatMessageAccumulator chatMessageAccumulator = mapStreamToAccumulator(sseModelApiResp.getFlowable())
                    .doOnNext(accumulator -> {
                        if (isFirst.getAndSet(false)) {
                            System.out.println("Response:");
                        }
                        if (accumulator.getDelta() != null && accumulator.getDelta().getTool_calls() != null) {
                            String jsonString = mapper.writeValueAsString(accumulator.getDelta().getTool_calls());
                            logger.info("tool_calls: {}", jsonString);
                            //responseContent.append("tool_calls: ").append(jsonString).append("\n");
                        }
                        if (accumulator.getDelta() != null && accumulator.getDelta().getContent() != null) {
                            String content = accumulator.getDelta().getContent();
                            System.out.print(content);
                            responseContent.append(content);
                        }
                        choices.add(accumulator.getChoice());
                    })
                    .doOnComplete(System.out::println)
                    .lastElement()
                    .blockingGet();

            ModelData data = new ModelData();
            data.setChoices(choices);
            data.setUsage(chatMessageAccumulator.getUsage());
            data.setId(chatMessageAccumulator.getId());
            data.setCreated(chatMessageAccumulator.getCreated());
            data.setRequestId(chatCompletionRequest.getRequestId());
            sseModelApiResp.setFlowable(null);// 打印前置空
            sseModelApiResp.setData(data);
        }

        logger.info("model output: {}", mapper.writeValueAsString(sseModelApiResp));
        responseContent.append(oldAchieve);

        return responseContent.toString();
    }

    /**
     * 更新人物社交关系
     */
    public static String updateCharacterRelationSSE(String oldRelation, String promptDesc, Date oldTime, Date now) throws JsonProcessingException {
        List<ChatMessage> messages = new ArrayList<>();

        /**
         * 这种形式下需要定期对所有社交关系进行整理
         */
        ChatMessage systemMessage = new ChatMessage(ChatMessageRole.SYSTEM.value(), "已知当前时间:" + now.toString() + "\n请分析用户提供的文本内容，按照格式输出你整理出来的所有人物社交关系。不要输出任何多余内容，不需要任何解释。用户提供的文本中可能没有提到社交关系，此时直接回答“----”。避免任何解释。\n输出格式:\n- 年份日期:(未知填不祥)\n  人物:\n  关系类型:(如朋友关系，父子关系、上下属关系等需要明确指出关系主体)");
        messages.add(systemMessage);
        ChatMessage userMessage = new ChatMessage(ChatMessageRole.USER.value(), "文本内容:" + promptDesc);
        messages.add(userMessage);

//        if(!oldRelation.isEmpty()){
//            ChatMessage systemMessage = new ChatMessage(ChatMessageRole.SYSTEM.value(), "请分析用户提供的文本内容，结合已知的人物社交关系输出更新后的人物社交关系。不要复述问题，不需要任何开头直接回答。用户提供的文本中可能没有提到社交关系，此时直接输出已知的人物社交关系，若没有则回答“无”。避免任何解释。");
//            messages.add(systemMessage);
//            ChatMessage sysMessage = new ChatMessage(ChatMessageRole.SYSTEM.value(), "已知的人物社交关系条目:" + oldRelation + "\n统计时间:" + oldTime.toString());
//            messages.add(sysMessage);
//            ChatMessage userMessage = new ChatMessage(ChatMessageRole.USER.value(), "文本内容:" + promptDesc + "\n当前时间:" + now.toString());
//            messages.add(userMessage);
//        }else{
//            ChatMessage systemMessage = new ChatMessage(ChatMessageRole.SYSTEM.value(), "请分析用户提供的文本内容，并仅输出你整理出来的人物社交关系。不要复述问题，不需要任何开头直接回答。用户提供的文本中可能没有提到社交关系，此时直接回答“无”。避免任何解释。");
//            messages.add(systemMessage);
//            ChatMessage userMessage = new ChatMessage(ChatMessageRole.USER.value(), "文本内容:" + promptDesc + "\n当前时间:" + now.toString());
//            messages.add(userMessage);
//        }

        String requestId = String.format(requestIdTemplate, System.currentTimeMillis());

        HashMap<String, Object> extraJson = new HashMap<>();

        //采样温度，控制输出的随机性，值越大随机性越强
        extraJson.put("temperature", 0.4);
        //单次响应tokens数限制，数值越大响应内容上限越大
        extraJson.put("max_tokens", 2048);

        ChatCompletionRequest chatCompletionRequest = ChatCompletionRequest.builder()
                .model(Constants.ModelChatGLM4)
                .stream(Boolean.TRUE)
                .messages(messages)
                .requestId(requestId)
                .toolChoice("auto")
                .extraJson(extraJson)
                .build();
        ModelApiResponse sseModelApiResp = client.invokeModelApi(chatCompletionRequest);

        StringBuilder responseContent = new StringBuilder();

        if (sseModelApiResp.isSuccess()) {
            AtomicBoolean isFirst = new AtomicBoolean(true);
            List<Choice> choices = new ArrayList<>();
            ChatMessageAccumulator chatMessageAccumulator = mapStreamToAccumulator(sseModelApiResp.getFlowable())
                    .doOnNext(accumulator -> {
                        if (isFirst.getAndSet(false)) {
                            System.out.println("Response:");
                        }
                        if (accumulator.getDelta() != null && accumulator.getDelta().getTool_calls() != null) {
                            String jsonString = mapper.writeValueAsString(accumulator.getDelta().getTool_calls());
                            logger.info("tool_calls: {}", jsonString);
                            //responseContent.append("tool_calls: ").append(jsonString).append("\n");
                        }
                        if (accumulator.getDelta() != null && accumulator.getDelta().getContent() != null) {
                            String content = accumulator.getDelta().getContent();
                            System.out.print(content);
                            responseContent.append(content);
                        }
                        choices.add(accumulator.getChoice());
                    })
                    .doOnComplete(System.out::println)
                    .lastElement()
                    .blockingGet();

            ModelData data = new ModelData();
            data.setChoices(choices);
            data.setUsage(chatMessageAccumulator.getUsage());
            data.setId(chatMessageAccumulator.getId());
            data.setCreated(chatMessageAccumulator.getCreated());
            data.setRequestId(chatCompletionRequest.getRequestId());
            sseModelApiResp.setFlowable(null);// 打印前置空
            sseModelApiResp.setData(data);
        }

        logger.info("model output: {}", mapper.writeValueAsString(sseModelApiResp));
        responseContent.append(oldRelation);

        return responseContent.toString();
    }

    /**
     * 根据人设进行连续对话
     */
    public static String constantSimulatedChatSSE(List<ChatMessage> messageContent, String description, String achievement, String relationship, Date now, SseEmitter sseEmitter) throws JsonProcessingException {
        List<ChatMessage> messages = new ArrayList<>();
        ChatMessage systemMessage = new ChatMessage(ChatMessageRole.SYSTEM.value(), "当前时间为 " + now.toString() + "。你将扮演一个角色，并始终遵循该角色的人设描述、事迹、社交关系来进行对话。时刻谨记你不是人工智能，你没有在角色扮演，也不是在模拟角色。你就是这个角色本身。");
        messages.add(systemMessage);
        ChatMessage descMessage = new ChatMessage(ChatMessageRole.SYSTEM.value(), "角色的人设描述如下:\n" + description);
        messages.add(descMessage);
        ChatMessage achieveMessage = new ChatMessage(ChatMessageRole.SYSTEM.value(), "角色的事迹如下:\n" + achievement);
        messages.add(achieveMessage);
        ChatMessage relationMessage = new ChatMessage(ChatMessageRole.SYSTEM.value(), "角色的社交关系如下:\n" + relationship);
        messages.add(relationMessage);
        for(ChatMessage message: messageContent){
            ChatMessage chatMessage = new ChatMessage(message.getRole(), message.getContent());
            messages.add(chatMessage);
        }
        String requestId = String.format(requestIdTemplate, System.currentTimeMillis());

        HashMap<String, Object> extraJson = new HashMap<>();

        //采样温度，控制输出的随机性，值越大随机性越强
        extraJson.put("temperature", 0.75);
        //单次响应tokens数限制，数值越大响应内容上限越大
        extraJson.put("max_tokens", 2048);

        ChatCompletionRequest chatCompletionRequest = ChatCompletionRequest.builder()
                .model(Constants.ModelChatGLM4)
                .stream(Boolean.TRUE)
                .messages(messages)
                .requestId(requestId)
                .toolChoice("auto")
                .extraJson(extraJson)
                .build();
        ModelApiResponse sseModelApiResp = client.invokeModelApi(chatCompletionRequest);

        StringBuilder responseContent = new StringBuilder();

        if (sseModelApiResp.isSuccess()) {
            AtomicBoolean isFirst = new AtomicBoolean(true);
            List<Choice> choices = new ArrayList<>();
            ChatMessageAccumulator chatMessageAccumulator = mapStreamToAccumulator(sseModelApiResp.getFlowable())
                    .doOnNext(accumulator -> {
                        if (isFirst.getAndSet(false)) {
                            System.out.println("Response:");
                        }
                        if (accumulator.getDelta() != null && accumulator.getDelta().getTool_calls() != null) {
                            String jsonString = mapper.writeValueAsString(accumulator.getDelta().getTool_calls());
                            logger.info("tool_calls: {}", jsonString);
                            //responseContent.append("tool_calls: ").append(jsonString).append("\n");
                        }
                        if (accumulator.getDelta() != null && accumulator.getDelta().getContent() != null) {
                            String content = accumulator.getDelta().getContent();
                            System.out.print(content);
                            responseContent.append(content);
                            if(sseEmitter != null){
                                sseEmitter.send(responseContent);
                            }
                        }
                        choices.add(accumulator.getChoice());
                    })
                    .doOnComplete(System.out::println)
                    .lastElement()
                    .blockingGet();

            if(sseEmitter != null){
                sseEmitter.onCompletion(() -> {
                    logger.info("sse output end_");
                });
            }
            ModelData data = new ModelData();
            data.setChoices(choices);
            data.setUsage(chatMessageAccumulator.getUsage());
            data.setId(chatMessageAccumulator.getId());
            data.setCreated(chatMessageAccumulator.getCreated());
            data.setRequestId(chatCompletionRequest.getRequestId());
            sseModelApiResp.setFlowable(null);// 打印前置空
            sseModelApiResp.setData(data);
        }

        logger.info("model output: {}", mapper.writeValueAsString(sseModelApiResp));

        return responseContent.toString();
    }

    /**
     * 流式stream输出
     */
    public static String chatStream(List<ChatMessage> messageContent, SseEmitter sseEmitter) throws JsonProcessingException {
        String requestId = String.format(requestIdTemplate, System.currentTimeMillis());

        HashMap<String, Object> extraJson = new HashMap<>();

        /**
         * 通过函数调用进行参数构建
         */
        List<ChatTool> chatToolList = new ArrayList<>();//创建工具类数组

        /**
         * 获取当前时间工具
         */
        ChatTool timeTool = new ChatTool();

        timeTool.setType(ChatToolType.FUNCTION.value());
        ChatFunctionParameters chatFunctionParameters = new ChatFunctionParameters();
        chatFunctionParameters.setType("object");
        Map<String, Object> properties = new HashMap<>();
        properties.put("format", new HashMap<String, Object>() {{
            put("type", "string");
            put("description", "时间格式，如：yyyy-MM-dd HH:mm:ss");
        }});
        chatFunctionParameters.setProperties(properties);
        ChatFunction chatFunction = ChatFunction.builder()
                .name("get_current_time")
                .description("Get the current time in a specified format")
                .parameters(chatFunctionParameters)
                .build();
        timeTool.setFunction(chatFunction);


        /**
         * 判断当前请求类型
         */

        chatToolList.add(timeTool);//添加到工具类数组
        /**
         * 函数调用参数构建结束
         */

        //采样温度，控制输出的随机性，值越大随机性越强
        //extraJson.put("temperature", 0.5);
        //单次响应tokens数限制，数值越大响应内容上限越大
        extraJson.put("max_tokens", 4095);

        ChatCompletionRequest chatCompletionRequest = ChatCompletionRequest.builder()
                .model(Constants.ModelChatGLM4)
                .stream(Boolean.TRUE)
                .messages(messageContent)
                .requestId(requestId)
                .toolChoice("auto")
                .extraJson(extraJson)
                .build();
        ModelApiResponse sseModelApiResp = client.invokeModelApi(chatCompletionRequest);

        StringBuilder responseContent = new StringBuilder();

        if (sseModelApiResp.isSuccess()) {
            AtomicBoolean isFirst = new AtomicBoolean(true);
            List<Choice> choices = new ArrayList<>();
            ChatMessageAccumulator chatMessageAccumulator = mapStreamToAccumulator(sseModelApiResp.getFlowable())
                    .doOnNext(accumulator -> {
                        if (isFirst.getAndSet(false)) {
                            System.out.println("Response:");
                        }
                        if (accumulator.getDelta() != null && accumulator.getDelta().getTool_calls() != null) {
                            String jsonString = mapper.writeValueAsString(accumulator.getDelta().getTool_calls());
                            System.out.println(accumulator.getDelta().getRole());
                            logger.info("tool_calls: {}", jsonString);
                            //responseContent.append("tool_calls: ").append(jsonString).append("\n");
                        }
                        if (accumulator.getDelta() != null && accumulator.getDelta().getContent() != null) {
                            String content = accumulator.getDelta().getContent();
                            System.out.print(content);
                            responseContent.append(content);
                            if(sseEmitter != null){
                                sseEmitter.send(responseContent);
                            }
                        }
                        choices.add(accumulator.getChoice());
                    })
                    .doOnComplete(System.out::println)
                    .lastElement()
                    .blockingGet();

            if(sseEmitter != null){
                sseEmitter.onCompletion(() -> {
                    logger.info("sse output end_");
                });
            }
            ModelData data = new ModelData();
            data.setChoices(choices);
            data.setUsage(chatMessageAccumulator.getUsage());
            data.setId(chatMessageAccumulator.getId());
            data.setCreated(chatMessageAccumulator.getCreated());
            data.setRequestId(chatCompletionRequest.getRequestId());
            sseModelApiResp.setFlowable(null);// 打印前置空
            sseModelApiResp.setData(data);

        }

        logger.info("model output: {}", mapper.writeValueAsString(sseModelApiResp));

        return responseContent.toString();
    }



    public static Flowable<ChatMessageAccumulator> mapStreamToAccumulator(Flowable<ModelData> flowable) {
        return flowable.map(chunk -> {
            return new ChatMessageAccumulator(chunk.getChoices().get(0).getDelta(), null, chunk.getChoices().get(0), chunk.getUsage(), chunk.getCreated(), chunk.getId());
        });
    }
}
